﻿using Microsoft.Extensions.DependencyInjection;
using System;

namespace Zeus.Mvc
{
    using Loggers;
    using Microsoft.AspNetCore.Builder;
    using Middlewares;
    using Results;
    using Results.Implementations;
    public static class ServiceDependencyInjection
    {
        public static IServiceCollection UseZeusResult(this IServiceCollection serviceCollection)
        {
            return serviceCollection
                .AddTransient<IZeusResultExecutor, ZeusResultExecutor>()
                .AddSingleton<IZeusResultFormatter, RequestGuidZeusResultFormatter>();

        }

        public static IServiceCollection UseZeusResult(this IServiceCollection serviceCollection, Type typeOfIZeusResultExecutor, Type typeOfIZeusResultFormatter)
        {
            if (typeOfIZeusResultExecutor == null && typeOfIZeusResultFormatter == null)
            {
                throw new ArgumentNullException($"{nameof(typeOfIZeusResultExecutor)} and {nameof(typeOfIZeusResultFormatter)}");
            }
            if (typeOfIZeusResultExecutor == null)
            {
                serviceCollection.AddTransient<IZeusResultExecutor, ZeusResultExecutor>();
            }
            else
            {
                serviceCollection.AddTransient(typeof(IZeusResultExecutor), typeOfIZeusResultExecutor);
            }
            if (typeOfIZeusResultFormatter == null)
            {
                serviceCollection.AddSingleton<IZeusResultFormatter, RequestGuidZeusResultFormatter>();
            }
            else
            {
                serviceCollection.AddSingleton(typeof(IZeusResultFormatter), typeOfIZeusResultFormatter);
            }
            return serviceCollection;
        }

        public static IServiceCollection UseZeusLogger<T>(this IServiceCollection serviceCollection, Type httpContextLoggerImplementations)
        {
            serviceCollection.AddTransient(typeof(IHttpContextLogger), httpContextLoggerImplementations);
            return serviceCollection;
        }

        public static IServiceCollection UseZeusLogger<T>(this IServiceCollection serviceCollection) where T : class, IHttpContextLogger
        {
            serviceCollection.AddTransient<IHttpContextLogger, T>();
            return serviceCollection;
        }

        public static IServiceCollection UseZeusLogger(this IServiceCollection serviceCollection, Type typeOfIHttpContextLogger)
        {
            if (typeOfIHttpContextLogger == null)
            {
                throw new ArgumentNullException(nameof(typeOfIHttpContextLogger));
            }
            serviceCollection.AddTransient(typeof(IHttpContextLogger), typeOfIHttpContextLogger);
            return serviceCollection;
        }

        public static IServiceCollection UseZeus(this IServiceCollection serviceCollection, ZeusMvcOptions zeusMvcOptions)
        {
            if (zeusMvcOptions.EnableZeusReuslt)
            {
                if (zeusMvcOptions.TypeOfIZeusResultExecutor == null && zeusMvcOptions.TypeOfIZeusResultFormatter == null)
                {
                    serviceCollection.UseZeusResult();
                }
                else
                {
                    serviceCollection.UseZeusResult(zeusMvcOptions.TypeOfIZeusResultExecutor, zeusMvcOptions.TypeOfIZeusResultFormatter);
                }
            }
            if (zeusMvcOptions.EnableLogger)
            {
                if (zeusMvcOptions.TypeOfIHttpContextLogger == null)
                {
                    throw new ArgumentNullException(nameof(zeusMvcOptions.TypeOfIHttpContextLogger));
                }
                else
                {
                    serviceCollection.UseZeusLogger(zeusMvcOptions.TypeOfIHttpContextLogger);
                }
            }
            return serviceCollection;
        }

        public static IApplicationBuilder UseZeusLogger(this IApplicationBuilder applicationBuilder)
        {
            return applicationBuilder.UseMiddleware<HttpContextLoggerMiddleware>();
        }

        public static IApplicationBuilder UseZeusCorrilationId(this IApplicationBuilder applicationBuilder)
        {
            return applicationBuilder.UseMiddleware<HttpCorrelationIdMiddleware>();
        }

        public static IApplicationBuilder UserZeus(this IApplicationBuilder applicationBuilder, ZeusMvcOptions zeusMvcOptions)
        {
            if (zeusMvcOptions.EnableCorrilationId)
            {
                applicationBuilder.UseZeusCorrilationId();
            }
            if (zeusMvcOptions.EnableLogger)
            {
                applicationBuilder.UseZeusLogger();
            }
        
            return applicationBuilder;
        }
    }
}
